STL 共有5 种迭代器分类,对应于它们支持的操作。
input 迭代器只能向前移动,一次一步,客户只可读取 (不能涂写)它们所指的东西,而且只能读取一次。它们模仿指向输入文件的阅读指针(readpointer) :C++程序库中的 istreamiterators 是这一分类的代表。Output迭代器情况类似,但一切只为输出 :它们只向前移动,一次一步,客户只可涂写它们所指的东西,而且只能涂写一次。 它们模仿指向输出文件的涂写指针(Writepointer) :ostreamiterators是这一分类的代表。这是威力最小的两个迭代器分类。由于这两类都只能向前移动,而且只能读或写其所指物最多一次,所以它们只适合“一次性操作算法” (one-pass algorithms) 。
另一个威力比较强大的分类是Forward 迭代器。这种迭代器可以做前述两种分类所能做的每一件事,而且可以读或写其所指物一次以上。这使得它们可施行于多次性操作算法(multi-pass algorithms)。STL 并未提供单向linked list,但某些程序库有 (通常名为 slist),而指入这种容器的迭代器就是属于Forward迭代器。指入 TRIhashed 容器 (见条款54) 的也可能是这一分类。(译注 : 这里说“可能”是因为hashed 容器的迭代器可为单向也可为双向,取决于实现版本。)
Bidirectional 迭代器比上一个分类威力更大: 它除了可以向前移动,还可以向后移动。STL 的 list迭代器就属于这一分类,set, multiset, map和 multimap 的迭代器也都是这一分类。
最有威力的迭代器当属 random access 迭代器。这种迭代器比上一个分类威力更大的地方在于它可以执行“迭代器算术〞,也就是它可以在常量时间内向前或向后跳跃任意距离。这样的算术很类似指针算术,那并不令人惊讶,因为random access 迭代器正是以内置 (原始)指针为榜样,而内置指针也可被当做random access迭代器使用。vector, deque和string提供的迭代器都是这一分类 。
对于这5 种分类,C++标准程序库分别提供专属的卷标结构 (tag struct)加以确认:
struct input_iterator_tag { };
struct output_iterator_tag { };
struct forward_iterator_tag: public input_iterator_tag { };
struct bidirectional_iterator_tag: public forward_iterator_tag { };
struct random_access_iterator_tag: public bidirectional_iterator_tag { }; 这些 structs 之间的继承关系是有效的 is-a 关系 (见条款32) :是的,所有forward迭代器都是input 迭代器,依此类推
模板特化是指针对特定类型的模板参数,提供特定的实现。模板偏特化是指针对模板参数的部分特化。
- 函数模板的特化
template<typename T>
void foo(T arg) {
// implementation for generic types
}
template<>
void foo<int>(int arg) {
// implementation for int type
} - 类模板的特化
template<typename T>
class MyTemplate {
// implementation for generic types
};
template<>
class MyTemplate<int> {
// implementation for int type
}; - 类模板的偏特化
template<typename T1, typename T2>
class Pair {
public:
T1 first;
T2 second;
};
// 对于指针类型的偏特化
template<typename T>
class Pair<T*, T*> {
public:
T* first;
T* second;
}; - 函数模板的偏特化
严格的来说,函数模板并不支持偏特化,但由于可以对函数进行重载,所以可以达到类似于类模板偏特化的效果。
template <class T> void f(T);
template <class T> void f(T*);